package reflect01;

import org.junit.Test;

import java.lang.reflect.Constructor;

/**
 * 反射(解剖出)字节码中的构造方法:
 * 基本 Java 类型（ boolean 、 byte 、 char 、 short 、 int 、 long 、 float和double）和关键字void也表示为Class对象。
 * 基本的类型包括void,直接通过xx.class代表对应的Class对象
 *
 *  借助于Class类中的方法:
 *    public Constructor<T> getConstructor(Class<?>... parameterTypes):
 *         形参代表获取指定参数的构造方法
 *         返回值代表将获取到的构造方法的各种信息封装到Constructor对象中
 *         它只能获取public修饰的构造方法
 *    public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes):
 *          形参代表获取指定参数的构造方法
 *          返回值代表将获取到的构造方法的各种信息封装到Constructor对象中
 *          它可以获取任意修饰的构造方法
 *   Constructor类中的方法:
 *     public void setAccessible(boolean flag):设置是否跳过对于java的权限访问检查,传入true则跳过，false则不跳过
 *     public String getName():获取构造方法的名称
 *     public T newInstance(Object ... initargs):根据指定的构造方法创建对象,如果构造方法需要传参,我们就要指定参数值,如果是空参构造不需要传参
 */
public class ReflectDemo02 {
    @Test
    public void testMethod01() throws Exception {
        //1.获取到Person类的字节码对象
        Class<Person> pCls = Person.class;

        //2.调用getConstructor获取构造方法
        Constructor<Person> pCon = pCls.getConstructor();

        //3.获取构造方法的名称
        System.out.println(pCon.getName());

        //4.利用Constructor创建对象
        Person p = pCon.newInstance();//类似早期: Person p = new Person();
        System.out.println(p);
    }

    /*利用空参构造快速创建对象
     * JDK 9之后不推荐使用
     * */
    @Test
    public void testMethod02() throws InstantiationException, IllegalAccessException {
        Person p = Person.class.newInstance();
        System.out.println(p);
    }

    /*获取有参构造*/
    @Test
    public void testMethod03()throws Exception{
        //1.获取要解刨的类的字节码对象
        Class<Person> pCls = (Class<Person>) Class.forName("reflect01.Person");

        //2.调用getConstructor获取指定的构造
        Constructor<Person> pCon =pCls.getConstructor(String.class, int.class);

        //3.利用构造方法创建对象
        Person person = pCon.newInstance("老王", 30);
        System.out.println(person);
    }

    @Test
    public void testMethod04()throws Exception{
        //1.获取要解刨的类的字节码对象
        Class<Person> pCls = Person.class;

        //2.获取指定的构造
        Constructor<Person> pCons = pCls.getDeclaredConstructor(String.class);

        /*Person person = pCons.newInstance("老王");
        System.out.println(person);*/

        //3.我们可以跳过java的权限访问检查(无视权限)
        pCons.setAccessible(true);

        //4.利用构造方法创建对象
        Person person = pCons.newInstance("老王");
        System.out.println(person);
    }


}
